package club.jdiy.dev.view;

import club.jdiy.core.base.domain.Pager;
import club.jdiy.dev.meta.ButtonMeta;
import club.jdiy.dev.meta.QoMeta;
import club.jdiy.core.sql.Rs;
import club.jdiy.utils.poi.MetaSet;

import java.util.List;
import java.util.Map;

public interface ListHandler extends TlBaseHandler {

    /**
     * 列表查询及顶部搜索控件渲染显示之前的拦截增强．
     * <br/><br/><strong>示例：</strong>(仅演示用法，不代表实际业务)<br/>
     * 场景介绍：假设当前列表是会员信息管理．
     * 对于超级管理员，可以管理所有地区的会员，但是对于某个地区管理员，只能管理他自己所在地区的会员数据．
     * 遇到这种情况，我们可以通过此增强器，在数据层面做额外的查询筛选过滤，
     * 或对相关搜索控件的屏蔽（如超级管理员顶上多一个按地区搜索的选择控件，
     * 但是对于区域管理员来说，他只能看到自己区域下的数据，因此不需要这个搜索控件，此时可以通过增强器将其移除不显示），
     * 伪代码示例如下（仅供参考）：
     * <pre>
     * public boolean beforeQuery(List&lt;QoMeta&gt; qos, ListWhere where) {
     *     User currentUser = context.getCurrentUser();//获取当前登录用户
     *     if(判断currentUser如果是区域管理员){   //具体判断条件跟据实际情况，此处略..
     *        where.and("o.area_id=3") //添加对应的条件，只查区域下的数据，根据实际情况添加条件
     *        //若不需要某个搜索控件，则将其从qos中移除
     *        qos.forEach(it->{
     *                 if("所在地区".equals(it.getLabel())) qos.remove(it);
     *             });
     *     }
     * }
     * &nbsp;@Resource
     * private AdminContext context;
     * </pre>
     *
     * @param qos   当前列表界面顶部的所有搜索控件列表（若将某个搜索控件移除，页面上将不显示）
     * @param where 附加查询条件对象．通过调用其and方法，可动态加添查询条件.  例如： where.and("o.state in (0,1,5) and o.area_id=3"
     */
    default void beforeQuery(List<QoMeta> qos, ListWhere where) {
    }

    /**
     * 系统会根据列表界面顶部配置的搜索控件，结合用户输入的搜索内容，添加相应动态条件查询；此方法对动态查询条件进行前置拦截增强.
     * <br/><br/><strong>示例：</strong>(仅演示用法，不代表实际业务)<br/>
     * 假设页面上有一个按订单状态(state)检索的下拉菜单（state状态值有：　<br/>
     * 0:待处理 1:已按单  2:待送货  3:送货中  4:已完成）．<br/>
     * 我们可以通过在线开发配置下拉菜单控件，搜索出对应状态的订单．但假如现在需要再增加一个＂处理中＂的查询，也就是把state=1,2,3这三种状态的一起查询出来，
     * 在线开发就满足不了这种要求了，此时我们就可以轻松通过onQuery增强处理来实现它！　<br/>
     * 实现方式：在配置下拉菜单的时候，我们为下拉菜单再增加一个额外的静态条目，比如： 99:处理中，此时下拉菜单的选项就变成了：<br/>
     * 0:待处理 1:已接单  2:待送货  3:送货中  4:已完成　99:处理中<br/>
     * 然后onQuery增强代码如下：
     *
     * <pre>
     * public boolean onQuery(QoMeta qo, String paramValue, ListWhere where) {
     *  　　if("state".equals(qo.field){   //确认是［状态搜索］这个下拉菜单控件
     *        if("99".equals(paramValue){
     *            where.and("o.state in (1,2,3)");
     *            return false;//指示JDiy后续代码不再处理此控件的查询条件(因为您这儿已处理过了，不然的话系统还会在后面再加上 where.and("o.state=99")
     *        }
     *     }
     *     return true;
     * }
     * </pre>
     *
     * @param qo         搜索控件的Meta配置信息. 因为列表界面上可以配置多个条件搜索控件，此参数用于区分是哪个控件(例如可以通过 qo.field获取到该控件绑定的搜索字段)
     * @param paramValue 该控件用户输入(或选择)的搜索内容．
     * @param where      附加查询条件对象．通过调用其and方法，可动态加添查询条件.  例如： where.and("o.state in (0,1,5) and o.name like '%"+paramValue+"%'")
     * @return 若此方法返回false, 则系统不再处理此控件的查询条件（也就是说您已经在方法内部处理了）；否则返回true,系统还会根据控件输入内容添加相应的动态查询条件．
     */
    default boolean onQuery(QoMeta qo, String paramValue, ListWhere where) {
        return true;
    }

    /**
     * 查询到当前页码的数据（带分页的数据记录集），在页面渲染显示前，对数据进行预处理增强．（例如可对部分字段内容修改或格式化, 统计值查询计算处理等）
     * <br/><br/><strong>示例：</strong>(仅演示用法，不代表实际业务)<br/>
     * 假设数据表中有一个hits字段，当其值小于100时，在页面上直接显示出来，否则页面上就只显示＂99+＂:<br/><br/>
     * <pre>
     * public void onView(Pager<Rs> pager) {
     *  　　for(Rs rs:pager.getItems()){
     *          Integer hits = rs.getInt("hits");
     *          if(hits!=null && hits>=100) rs.set("hits","99+");
     *     }
     * }
     * </pre>
     *
     * @param pager 当前页的数据及相关页码信息
     * @param qo    (Query Objects的简写)，储存了用户输入的搜索条件(即Key/Value形式的Map键值对)，
     *              其健名Key=搜索控件ID, 即您可以通过ID获取到控件的用户输入，以便增强处理（如针对表格中的每行数据(pager.items)，
     *              到其它子表中汇总统计，并将统计结果赋予数据行的某个自定义字段（配置列表某列显示出这个自定义字段）即可
     */
    default void onView(Pager<Rs> pager, Map<String, String> qo) {
    }

    /**
     * 对数据行右边管理栏中的按钮进行增强处理．比如根据自定义的条件判断按钮是否显示，改变数据行按钮相关Meta属性等．<br/>
     * <br/><strong>示例：</strong>(仅演示用法，不代表实际业务)<br/><br/>
     * 假如数据记录有一个state字段，当其值为1时，不显示[删除]按钮, 当state=2时，[修改]按钮的背景显示为红色：<br/><br/>
     * <pre>
     * public boolean onButton(ButtonMeta buttonMeta, Rs rowData) {
     *      int state = rowData.getInt("state");
     *  　　//下行用于判断是[删除]按钮. 当然也可以通过 buttonMeta.getText()判断按钮类型
     *     if(buttonMeta.getAct()==BtnActTpl.del){
     *         return state!=1; //state=1时，返回false,也就是该按钮不在页面上显示
     *
     *     }else if(buttonMeta.getAct()==BtnActTpl.edit){//是[修改]按钮
     *         if(state==2) buttonMeta.setBg("#ff0000"); //当记录的state==2时,设置[修改]按钮背景为红色
     *     }
     *     return true;//返回true，显示该按钮
     *
     * }
     * </pre>
     *
     * @param buttonMeta button的Meta配置信息．因为一个界面上可以配置多个按钮，此参数用来区分是哪个按钮，同时可修改目标按钮相应字段的值改变其属性或行为.
     * @param rowData    当前行数据
     * @return 若返回false, 则不显示目标按钮
     */
    default boolean onButton(ButtonMeta buttonMeta, Rs rowData) {
        return true;
    }


    /**
     * 对列表上方的管理按钮进行增强处理．比如根据自定义的条件判断按钮是否显示，改变按钮相关Meta属性等．<br/>
     * <br/><strong>示例：</strong>(仅演示用法，不代表实际业务)<br/><br/>
     * <pre>
     * public boolean onButton(ButtonMeta buttonMeta) {
     *      if (context.hasRole(1) != null) {//jdiy_role.id=1,是超级管理员身份
     *             //相关代码略。一般是修改此buttonMeta的相关属性，比如设置按钮点击后的目标界面URL地址参数等等.
     *         }
     *     return true;//返回true，显示该按钮.  若为false,该按钮就不显示在页面上了。
     *
     * }
     * </pre>
     *
     * @param buttonMeta button的Meta配置信息．用于区分当前是对哪个按钮进行增强处理.
     * @return 若返回false, 则不显示目标按钮
     */
    default boolean onButton(ButtonMeta buttonMeta) {

        return true;
    }


    /**
     * 自定义Excel导出,定义导出头元信息.<br/>
     * 若返回非空，且长度非0的MetaSet数组，则以该数组定义的表头元进行数据导出。
     * 否则以列表界面表格显示的字段顺序进行导出。<br/>
     * <strong>自定义格式导出示例：</strong>
     * <pre>
     * public MetaSet[] customExport() {
     *        return new MetaSet[]{
     *               new MetaSet("姓名", "name"),   //MetaSet的每一个元素，对应于一个导出列：详见{@link MetaSet}类的各构造函数的用法.
     *               new MetaSet("年龄", "age"),
     *               new MetaSet("住址", 200, "addr"), //200:自定义该列显示的宽度
     *               new MetaSet("班主任姓名", "teacherName"),  //子成员变量
     *               new MetaSet("是否欠费", "qianFei"), //boolean字段导出为：是|否
     *               new MetaSet("注册时间", "dtAdd"), //LocalDate自动格式化为：yyyy-MM-dd, LocalDateTime自动格式化为：yyyy-MM-dd HH:mm:ss
     *               new MetaSet("性别", new Formatter&lt;Rs&gt;() {   //指定一个Formatter&lt;Rs&gt;函数进行自定义的格式化输出（常规写法）
     *                   public Object fmt(Rs rowData) {//格式化输出，返回格式化后的数据.  rowData表示当前行
     *                       return rowData.getInt("gender")==1 ? "男":"女";
     *                   }
     *               }),
     *               new MetaSet("性别2", (Formatter&lt;Rs&gt;) o -> gender==1?"男":"女" )   //自定义的格式化输出(这是lambla表达式的简写形式)
     *       }
     * }
     * </pre>
     *
     * @return 导出的表头Meta定义元信息
     */
    default MetaSet[] customExport() {
        return null;
    }


}
